﻿
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace DotNet.Utilities.List和Datatable转换
{
    public  static class LDHelper
    {
        #region 实体转化为DataTable
        /// <summary>
        /// 将实体类集合转化为datetable
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="models"></param>
        /// <returns>datatable</returns>
        public static DataTable GetTableByEntity<T>(this IEnumerable<T> models, bool Second = true,bool IsDeclaring=true) where T : class
        {

            DataTable dt = new DataTable();
            //设置表头
            PropertyInfo[] pros = typeof(T).GetProperties();
            if (IsDeclaring)
            {
               pros=pros.Where(x => x.DeclaringType == typeof(T)).ToArray();
            }

            foreach (System.Reflection.PropertyInfo pi in pros)
            {

                try
                {
                    //pi.DeclaringType != typeof(T) 
                    if (pi != null &&pi.PropertyType!=typeof(Nullable)&&pi.PropertyType!=typeof(Nullable<System.DateTime>))
                        dt.Columns.Add(pi.Name, System.Type.GetType(pi.PropertyType.ToString()));
                }
                catch (Exception)
                {
                    continue;
                }

            }
            //通过两种不同的方式像表格中添加数据
            if (Second)
            {
                //逐行加入数据
                foreach (T item in models)
                {
                    DataRow row = dt.NewRow();
                    foreach (var pi in pros)
                    {
                        object propertyValue = pi.GetValue(item, null);
                        if (propertyValue != null && propertyValue != DBNull.Value)
                            row[pi.Name] = pi.GetValue(item, null);
                    }
                    dt.Rows.Add(row);
                }
            }
            else
            {
                //逐行加入数据
                foreach (T item in models)
                {
                    object[] itm = new object[pros.Length];//保存每个属性的值
                    int index = 0;//表示要放到object的位置
                    foreach (var pi in pros)
                    {
                        itm.SetValue(pi.GetValue(item, null), index);
                        index++;//数组下标依次加一
                    }

                    //将obect放到dt的row中
                    dt.LoadDataRow(itm, true);
                }
            }
            //返回
            return dt;
            ////将DateTable放入DataSet
            //RDS.Tables.Add(TempDT);
            ////返回DataSet

        }
        #endregion



        //#region 实体转化为DataTable
        ///// <summary>
        ///// 将实体类集合转化为datetable
        ///// </summary>
        ///// <typeparam name="T"></typeparam>
        ///// <param name="models"></param>
        ///// <returns>datatable</returns>
        //public static DataTable GetTableByEntity<T>(this IEnumerable<T> models, bool Second = true) where T : class
        //{
           
        //    DataTable dt = new DataTable();
        //    //设置表头
        //    System.Reflection.PropertyInfo[] pros = typeof(T).GetProperties();
        //    foreach (System.Reflection.PropertyInfo pi in pros)
        //    {

        //        try
        //        {
        //            dt.Columns.Add(pi.Name, System.Type.GetType(pi.PropertyType.ToString()));
        //        }
        //        catch (Exception)
        //        {
        //            continue;
        //        }

        //    }
        //    //通过两种不同的方式像表格中添加数据
        //    if (Second)
        //    {
        //        //逐行加入数据
        //        foreach (T item in models)
        //        {
        //            DataRow row = dt.NewRow();
        //            foreach (var pi in pros)
        //            {
        //                object propertyValue = pi.GetValue(item, null);
        //                if (propertyValue != null)
        //                    row[pi.Name] = pi.GetValue(item, null);
        //            }
        //            dt.Rows.Add(row);
        //        }
        //    }
        //    else
        //    {
        //        //逐行加入数据
        //        foreach (T item in models)
        //        {
        //            object[] itm = new object[pros.Length];//保存每个属性的值
        //            int index = 0;//表示要放到object的位置
        //            foreach (var pi in pros)
        //            {
        //                itm.SetValue(pi.GetValue(item, null), index);
        //                index++;//数组下标依次加一
        //            }

        //            //将obect放到dt的row中
        //            dt.LoadDataRow(itm, true);
        //        }
        //    }
        //    //返回
        //    return dt;
        //    ////将DateTable放入DataSet
        //    //RDS.Tables.Add(TempDT);
        //    ////返回DataSet

        //}
        //#endregion

        #region 根据datatable得到实体集合
        public static IEnumerable<T> EntityListGet<T>( this DataTable table) where T : class
        {
            List<T> entityList = new List<T>();
            if (table != null && table.Rows.Count > 0)
            {
                foreach (DataRow dr in table.Rows)
                {
                    T entity = (T)Activator.CreateInstance(typeof(T));
                    for (int i = 0; i < dr.Table.Columns.Count; i++)
                    {
                        PropertyInfo propertyInfo = entity.GetType().GetProperty(dr.Table.Columns[i].ColumnName);
                        if (propertyInfo != null && dr[i] != DBNull.Value)
                        {
                            propertyInfo.SetValue(entity, dr[i], null);
                        }
                    }
                    entityList.Add(entity);
                }
            }
            return entityList;
        }

        //private static IEnumerable<T> GetEntityListByTable<T>(DataTable dt) where T : class
        //{
        //    PropertyInfo[] pis = typeof(T).GetProperties();
        //    var query=
        //        from p in dt.AsEnumerable()
        //        select new 
        //        {

        //        }
        //}
        #endregion

        #region 利用dic和string创建表格
        /// <summary>
        /// 利用dic （存储列名和列的类型）和string类型(每行的数据 用逗号分割)创建table 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dic">存储列名和列的类型</param>
        /// <param name="colData">每行的数据 用逗号分割</param>
        /// <returns></returns>
        public static DataTable CreateTable(Dictionary<string, string> dic, List<string[]> colData) 
        {
            DataTable dt = new DataTable();
            //通过dic的键值对 来配置表格的列
            foreach (var item in dic)
            {

                DataColumn dc = new DataColumn(item.Key.ToString(), Type.GetType("System." + item.Value.ToString()));
                dt.Columns.Add(dc);
            }
            foreach (var item in colData)
            {
                DataRow dr = dt.NewRow();
                //List<string> strList = StringHelper.GetStrArray(item, ',', false);

                for (int i = 0; i < item.Length; i++)
                {
                    dr[dic.Keys.ToList()[i].ToString()] = item[i];
                }
                dt.Rows.Add(dr);
                //dic.Keys.ToList().ForEach(x=>dr[x.ToString()]=)
            }
            return dt;
        } 
        #endregion

        #region 表格转换为文件
        /// <summary>
        /// 表格转换txt DataTableChangeTxt(dt,path)表示将datatable 转化到指定路径的文件
        /// </summary>
        /// <param name="dt">表格</param>
        /// <param name="path">path</param>
        /// <returns></returns>
        public static string DataTableToTxt( DataTable dt, string path)
        {
            try
            {
                // 使用制表符 \t 分隔每行中的列数据
                //得到列的str
                var rowCol = new List<string>{StringHelper.GetArrayStr( dt.Columns.Cast<DataColumn>()
                .Select(item => item.ColumnName).ToList(),"\t")};
                //get row str
                var rows = dt.Rows.Cast<System.Data.DataRow>()
                    .Select(item => string.Join("\t", item.ItemArray));
                //union column and row
                var dtStr = rowCol.Concat(rows);
                System.IO.File.WriteAllLines(path, dtStr, Encoding.UTF8);
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
            return "操作成功";
        } 
        #endregion

        #region 文件转化为表格
        /// <summary>
        /// 文件转化为表格 FileToDataTable("c:/1.txt",new Dictionary<string,string>() )
        /// </summary>
        /// <param name="path">路径</param>
        /// <param name="dic">列名和类型的键值对</param>
        /// <returns></returns>
        public static DataTable FileToDataTable(string path,  Char[] spreated,Dictionary<string, string> dic = null)
        {
            List<string[]> contents = FileUtil.GetFileContentByLinq(path, spreated);
            //如果没传值的话 那么就是默认从文件里面 文件的第一行读取表头 类型默认全是string类型
            if (dic == null)
            {
                dic = new Dictionary<string, string>();
                foreach (var item in contents[0])
                {
                    dic[item.ToString()] = "String";
                }
                contents.RemoveAt(0);//移除表头
                return CreateTable(dic, contents);
            }
            return CreateTable(dic, contents);
        } 
        #endregion
    }
}